home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 22
/
Aminet 22 (1997)(GTI - Schatztruhe)[!][Dec 1997].iso
/
Aminet
/
dev
/
e
/
ebuild.lha
/
ebuild
/
Build.e
< prev
next >
Wrap
Text File
|
1997-09-21
|
12KB
|
433 lines
/* build in E.
TODO: - cyclic structure check (part)
- (amigados?) constants (part)
*/
OPT OSVERSION=37
MODULE 'tools/file', 'dos/dosextens', 'dos/dos'
/*
symbol=object
object: dep1 dep2 ....
act1
act2
$(symbol): $(symbol)bla ....
act1
...
*/
/*
history:
(Version 0.8 by Rob and Wouter)
When Who What
23.07.97 Glauschwuffel - Added symbolic constants. Constants are allowed everywhere
26.07.97 Glauschwuffel - Removed bug in constants: The part after the last constant
wouldn't be copied. $(test): $(test).e crashed in cyclic
dependancy. :(
- Used source that Jason mailed me to get right order of actions.
- Minor modification in traverse(): "circ" is raised when object
and a dependancy have the same name.
- Added version facility :)
- local constant $(target) is now available in actions
- Added QUIET arg
27.07.97 Glauschwuffel - Changed QUIET to VERBOSE since quiet was default for v3.1
(between Glauschwuffel - Used EBuild with new oomodules/ objects. *Very* stable, no errrors
at all. I tend to say it's error-free <g>)
09.08.97 Glauschwuffel - Actions of a target are now collected in a script again.
EBuild now acts as described in the Ev3.2 doc (except of the
modified $target). Bumped version to 0.9.
10.08.97 Glauschwuffel - Added script variable $target for reasons of consistency. Now
$(target) and $target are possible.
Discovered a potential bug: if build is called without a target and
the first target in the buildfile is not a filename (e.g. a symbolic
target like `all' or `clean') the actions for this target are
executed anyway (0.8 does this, too).
05.09.97 Glauschwuffel - BUG: the temporary script in T: won't be closed if an exception
raised. Removed.
13.09.97 Glauschwuffel - ADD: commandline option CONSTANTS. Lists the constants before executing
anything. Modified `dumpC()' for this.
*/
OBJECT object
next:PTR TO object
name:PTR TO CHAR
firstdep:PTR TO dependancy
firstaction:PTR TO action
child
lastaction:PTR TO action
ENDOBJECT
OBJECT dependancy
next:PTR TO dependancy
object:PTR TO object
ENDOBJECT
OBJECT action
next:PTR TO action
comstring:PTR TO CHAR
ENDOBJECT
OBJECT arg
target,buildfile,force,verbose,nohead,constants
ENDOBJECT
OBJECT constant
next:PTR TO constant
name:PTR TO CHAR
subst:PTR TO CHAR
ENDOBJECT
DEF curline=0, curstring, uptodate=TRUE, args:PTR TO arg,
constants:PTR TO constant, -> global list of constants in reverse order
target:PTR TO CHAR -> holds name of current target
PROC main() HANDLE
DEF m,l,buildfile[200]:STRING,rdargs=NIL
NEW args
IF (rdargs:=ReadArgs('TARGET,FROM/K,FORCE/S,VERBOSE/S,NOHEAD/S,CONSTANTS/S',args,NIL))=NIL THEN Raise("barg")
IF args.buildfile THEN StrCopy(buildfile,args.buildfile)
StrAdd(buildfile,'.build')
IF (args.nohead = 0) -> be VERY quiet
PrintF({versionString})
PrintF(' (processing "\s")\n', buildfile)
ENDIF
m,l:=readfile(buildfile)
buildtree(parse(stringsinfile(m,l,countstrings(m,l))))
IF uptodate THEN PrintF('All files are up to date.\n')
Raise()
EXCEPT
IF rdargs THEN FreeArgs(rdargs)
IF exception=0 THEN RETURN
PrintF('Error: ')
SELECT exception
CASE "OPEN"
PrintF('couldn''t open "\s".\n',exceptioninfo)
CASE "MEM"
PrintF('not enough memory.\n')
CASE "IN"
PrintF('couldn''t read file.\n')
CASE "nobj"
PrintF('action without object.\n')
CASE "fexp"
PrintF('filename expected.\n')
CASE "dexp"
PrintF('":" or "=" expected.\n')
CASE "empt"
PrintF('nothing to build.\n')
CASE "circ"
PrintF('circular dependancies at file "\s".\n', exceptioninfo)
CASE "bada"
PrintF('action failed to build "\s".\n',exceptioninfo)
CASE "badd"
PrintF('dependancy "\s" not available.\n',exceptioninfo)
CASE "derr"
PrintF('child process failed.\n')
CASE "ntar"
PrintF('no such target: "\s".\n',args.target)
CASE "ndep"
PrintF('no dependancies for object "\s".\n',exceptioninfo)
CASE "clos"
PrintF('missing closing brace: "\s".\n',exceptioninfo)
CASE "cons"
PrintF('unknown constant: "\s".\n',exceptioninfo)
CASE "barg"
PrintFault(IoErr(),NIL)
CASE "scrp"
PrintF ('unable to create temporary script.\n')
DEFAULT
PrintF('burp.\n')
ENDSELECT
IF curline THEN PrintF('at line: (\d) "\s"\n',curline,curstring)
IF exception THEN PrintF('Build terminated\n')
RETURN 10
ENDPROC
PROC parse(list:PTR TO LONG)
DEF l=NIL:PTR TO object, s, c, i, t, const=NIL:PTR TO constant,str:PTR TO CHAR
FOR curline:=0 TO ListLen(list)-1
s:=list[curline]
curstring:=s
c:=s[]
IF (c<>"#") AND (c<>"\0") -> ignore?
IF (c=" ") OR (c="\t") -> action
s:=eatwhite(s)
IF s[]
IF l=NIL THEN Raise("nobj")
-> was: l.firstaction:=NEW [l.firstaction,s]:action
-> replaced by the following IF (Rob through Glauschwuffel)
IF l.lastaction
l.lastaction.next:=NEW [NIL,s]:action
l.lastaction:=l.lastaction.next
ELSE
l.firstaction:=NEW [NIL,s]:action
l.lastaction:=l.firstaction
ENDIF
ENDIF
ELSE -> object rule or constant
i:=s
s:=eatname(s)
IF s=i THEN Raise("fexp")
t:=s
IF (s[]<>":") AND (s[]<>"=") THEN Raise("dexp")
IF s[]=":"
-> check object rule for use of constants
str:=String(1024) -> dyn. alloc., free if no constants
IF str=NIL THEN Raise("MEM")
/* IF (substituteConstants (i, str)<>0) ->update vars if there were constants
i := str; s:=eatname(str) -> these were copied from above
IF s=i THEN Raise("fexp")
t:=s
ELSE
Dispose(str)
ENDIF
*/
substituteConstants (i, str)
i := str; s:=eatname(str)
IF s=i THEN Raise("fexp")
t:=s
t[]:="\0"
s++
s:=eatwhite(s)
l:=NEW [l,i,NIL,NIL,0]:object
s:=eatwhite(s)
IF s[]<>"\0"
REPEAT
i:=s
s:=eatname(s)
t:=s
IF t=i THEN Raise("fexp")
s:=eatwhite(s)
t[]:="\0"
l.firstdep:=NEW [l.firstdep,i]:dependancy
UNTIL s[]="\0"
ENDIF
ELSE -> we have a constant
s++
s:=eatwhite(s)
t[]:="\0" -> terminate name
const:=NEW[const,i,s]:constant
constants:=const -> have to do it here so consts in rules are recognized
ENDIF
ENDIF
ENDIF
ENDFOR
curline:=0
IF args.constants THEN dumpC()
IF l=NIL THEN Raise("empt")
ENDPROC l
PROC eatwhite(s)
WHILE (s[]=" ") OR (s[]="\t") DO s++
ENDPROC s
PROC eatname(s)
WHILE (s[]<>" ") AND (s[]<>"\t") AND (s[]<>"\0") AND (s[]<>":") AND (s[]<>"=") DO s++
ENDPROC s
/* obsolete
PROC execute(c)
DEF s[1024]:STRING
uptodate:=FALSE
substituteConstants (c, s)
IF args.verbose THEN PrintF('\t\s\n', s)
-> PrintF('\t\s\n',IF substituteConstants (c, s) THEN s ELSE c)
IF Execute(s,NIL,stdout)=NIL THEN Raise("derr")
ENDPROC */
PROC filetime(name:PTR TO CHAR)
DEF l:PTR TO filelock, fib:fileinfoblock, date:PTR TO datestamp
IF l:=Lock(name,ACTION_READ)
IF Examine(l,fib)
date:=fib.datestamp
IF fib.direntrytype<0
UnLock(l)
RETURN date.days, Shl(date.minute,12)+date.tick
ENDIF
ENDIF
UnLock(l)
ENDIF
ENDPROC -1
PROC timelater(day1,tick1,day2,tick2)
IF day1>day2
RETURN TRUE
ELSEIF day1=day2
RETURN tick1>tick2
ENDIF
ENDPROC FALSE
/*----------------rob's-stuff-------------------*/
PROC buildtree(list:PTR TO object) -> returns root of tree
DEF dep:PTR TO dependancy,
obj:PTR TO object
obj:=list
WHILE obj -> traverse objects
dep:=obj.firstdep
WHILE dep -> traverse dependencies
dep.object:=findobject(dep.object,list)
dep:=dep.next
ENDWHILE
obj:=obj.next
ENDWHILE
-> CHECK CYCLES!!!
obj:=list
IF args.target
WHILE obj
IF StrCmp(args.target,obj.name) THEN JUMP out
obj:=obj.next
ENDWHILE
Raise("ntar")
out:
ELSE
IF obj THEN WHILE obj.next DO obj:=obj.next
ENDIF
traverse(obj)
ENDPROC
-> find object in list of objects by name
PROC findobject(name:PTR TO CHAR,list:PTR TO object)
WHILE list
IF StrCmp(name,list.name)
-> remove object from root list
list.child:=TRUE;
RETURN list
ENDIF
list:=list.next
ENDWHILE
ENDPROC NEW [NIL,name,NIL,NIL]:object
-> child-first traversal of dependancy tree
PROC traverse(obj:PTR TO object) -> executes actions in tree
DEF dep:PTR TO dependancy,maxtime1=0,maxtime2=0,time1,time2,action:PTR TO action
IF obj.firstdep OR obj.firstaction -> object with dependancies/actions
-> traverse children and get maximum timestamp
dep:=obj.firstdep
WHILE dep
IF OstrCmp (dep.object.name, obj.name) = 0 THEN Throw("circ",obj.name) -> cyclic check by Glauschwuffel
target := obj.name
time1,time2:=traverse(dep.object)
IF timelater(time1,time2,maxtime1,maxtime2)
maxtime1:=time1
maxtime2:=time2
ENDIF
dep:=dep.next
ENDWHILE
time1,time2:=filetime (obj.name)
IF time1<0 OR timelater(maxtime1,maxtime2,time1,time2) OR args.force
-> dependancy file(s) more recent: build object
-> execute actions
action:=obj.firstaction
buildAndExecuteScript (action)
time1,time2:=filetime(obj.name)
IF (time1<0) AND (obj.child=TRUE) THEN Throw("bada",obj.name)
ENDIF
RETURN time1,time2
ENDIF
-> object requires no action: return timestamp
time1,time2:=filetime(obj.name);
IF time1<0 THEN Throw("badd",obj.name)
ENDPROC time1,time2
/* - glauschwuffel's stuff --- */
PROC dumpC()
DEF co:PTR TO constant
co:=constants
WriteF ('Constants are:\n')
WHILE co
WriteF('\t<\s> with <\s>.\n', co.name, co.subst)
co:=co.next
ENDWHILE
ENDPROC
PROC substituteConstants(c:PTR TO CHAR, s:PTR TO CHAR)
-> search c for constants and substitute them
DEF dollar, bclose=-1,sub=NIL
REPEAT
bclose++
dollar := InStr (c,'$(',bclose)
IF (dollar<>-1) -> found it?
StrAdd (s, c+bclose, dollar-bclose)
bclose := InStr (c,')',dollar+2)
IF bclose=-1 THEN Throw("clos",c)
sub := findConstant(c,dollar+2,bclose-1)
IF sub=NIL THEN Throw("cons",c+dollar)
StrAdd (s,sub)
ELSE -> copy rest of the line to buffer
StrAdd (s, c+bclose)
ENDIF
UNTIL (dollar=-1) OR (bclose=-1)
RETURN sub -> did we substitute something at all?
ENDPROC
PROC findConstant(c,start,end)
-> find constant of given position in list
-> add 27.07.97: returns global target on target
DEF co:PTR TO constant
IF OstrCmp('target',c+start,end-start+1)=0 THEN RETURN target
co:=constants
WHILE co
EXIT (OstrCmp(co.name,c+start,end-start+1)=0)
co:=co.next
ENDWHILE
RETURN IF co THEN co.subst ELSE NIL
ENDPROC
PROC buildAndExecuteScript (action:PTR TO action) HANDLE
DEF s[1024]:STRING,
handle
handle := Open ('T:Ebuild_actions', MODE_NEWFILE) -> open script file
IF (handle = NIL) THEN Raise ("scrp")
/* create script variable TARGET */
StrCopy (s, 'Set target ')
StrAdd (s, target)
StrAdd (s, '\n') -> add newline
Write (handle, s, StrLen (s))
IF args.verbose THEN PrintF('\t\s', s)
WHILE action
uptodate:=FALSE
SetStr (s, 0) -> "delete" the string of the last action
substituteConstants (action.comstring, s) -> expand action
StrAdd (s, '\n') -> add newline
IF args.verbose THEN PrintF('\t\s', s)
Write (handle, s, StrLen (s))
action:=action.next
ENDWHILE
Close (handle)
IF Execute('Execute T:Ebuild_actions', NIL, stdout)=NIL THEN Raise("derr")
DeleteFile ('T:EBuild_actions')
EXCEPT
IF handle THEN Close(handle)
ReThrow()
ENDPROC
versionTag: CHAR 0,'$VER:'
versionString: CHAR 'EBuild 0.91 (05.09.97) ©1997 Rob, Wouter and Glauschwuffel',0